{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/vb/anaconda3/lib/python3.7/site-packages/matplotlib/__init__.py:846: MatplotlibDeprecationWarning: \n",
      "The text.latex.unicode rcparam was deprecated in Matplotlib 2.2 and will be removed in 3.1.\n",
      "  \"2.2\", name=key, obj_type=\"rcparam\", addendum=addendum)\n",
      "/Users/vb/anaconda3/lib/python3.7/site-packages/matplotlib/__init__.py:855: MatplotlibDeprecationWarning: \n",
      "examples.directory is deprecated; in the future, examples will be found relative to the 'datapath' directory.\n",
      "  \"found relative to the 'datapath' directory.\".format(key))\n",
      "/Users/vb/anaconda3/lib/python3.7/site-packages/matplotlib/__init__.py:947: UserWarning: could not find rc file; returning defaults\n",
      "  warnings.warn(message)\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import numpy.linalg as npl\n",
    "import math\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 6.1 Matrices"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[ 0. ,  1. , -2.3,  0.1],\n",
       "        [ 1.3,  4. , -0.1,  0. ],\n",
       "        [ 4.1, -1. ,  0. ,  1.7]])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = np.matrix([[0.0, 1.0, -2.3, 0.1], [1.3, 4.0, -0.1, 0.0],[4.1,-1.0, 0.0, 1.7]])\n",
    "A #in Julia you ommit the multiple array brackets and commas, \n",
    "  #and use semi colons to break rows"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3, 4, 3, 4)"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m,n = np.shape(A) #J: m,n = size(A)\n",
    "m,n, np.shape(A)[0],np.shape(A)[1] #J: size(A,1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "isTall = lambda x: np.shape(A)[0] > np.shape(A)[1] #J: size(X,1)>size(X,2)\n",
    "isTall(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(-0.1, -2.3, -1.0)"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A[1,2], A[0,2], A[2,1] #Coordinates can be interpreted as y,x\n",
    "                       #or list index, item index"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Z = np.matrix([[-1,0,2],[-1,2,-3]])\n",
    "Z[1,1] #J: Z[5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(False, matrix([[ True,  True,  True,  True],\n",
       "         [ True, False,  True,  True],\n",
       "         [ True,  True,  True,  True]]))"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B = A.copy()\n",
    "B[1,1] = 0\n",
    "np.array_equal(A,B), A==B #J: second eval would get first result , second result done with .="
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(11, matrix([[3, 2, 3, 3]]))"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sum(A==B), sum(A==B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(matrix([[-2.1, -3. ,  0. ]]), array([-2.1, -3. ,  0. ]))"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.matrix([-2.1, -3, 0])\n",
    "b = np.array([-2.1, -3, 0])\n",
    "a,b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[-1,  0,  1,  0],\n",
       "        [ 2, -3,  0,  1],\n",
       "        [ 0,  4, -2,  1]])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = np.matrix([[-1, 0, 1, 0], [2,-3,0,1],[0,4,-2,1]])\n",
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[1, 0],\n",
       "        [0, 1]])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A[0:2,2:4] \n",
    "\n",
    "#in J: [1:2,3:4]\n",
    "#difference because 1) 0 indexing vs 1 indexing\n",
    "#                   2) slice value exclusive vs inclusive\n",
    "#                   ie: [0:2] in python says lists 0 and 1\n",
    "#                       [1:2] in julia says lists 1 and 2               "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[ 1],\n",
       "        [ 0],\n",
       "        [-2]])"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A[:,2] #J: [:,3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(matrix([[ 2, -3,  0,  1]]), matrix([[ 2, -3,  0,  1]]))"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.vstack(A[1,:]),A[1,:]\n",
    "#J: this *row* will automatically get returned as a *col* (???)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[ 0,  4, -2,  1],\n",
       "        [ 2, -3,  0,  1],\n",
       "        [-1,  0,  1,  0]])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m = np.shape(A)[0]\n",
    "A[::-1] #J: [m:-1:1,:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[ 1, -3],\n",
       "        [ 2,  0],\n",
       "        [ 1, -2]])"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B = np.matrix([[1,-3],[2,0],[1,-2]])\n",
    "B"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[ 1, -3,  2,  0,  1, -2]])"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.vstack(B.flatten())\n",
    "# J: B[:]\n",
    "#can also use: np.matrix(B.A1).transpose(), B.ravel().transpose()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[ 1, -3,  2],\n",
       "        [ 0,  1, -2]])"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.reshape(B,(2,3))\n",
    "# Here numpy reads the matrix from left to right as it originally was\n",
    "# and writes them row wise\n",
    "# In Julia (2,3) reads the first values in each list, and writes them\n",
    "# column wise:\n",
    "# 1 1 0\n",
    "# 2 -3 -2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[ 0,  2,  3, -1],\n",
       "        [ 2,  2,  1,  4],\n",
       "        [ 1,  3,  5,  4]])"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B = np.matrix([0,2,3])\n",
    "C = np.matrix([-1])\n",
    "D = np.matrix([[2,2,1],[1,3,5]])\n",
    "E = np.matrix([[4],[4]])\n",
    "A = np.block([[B,C],[D,E]]) #J: A = [B C; D E]\n",
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 2.],\n",
       "       [4., 5.],\n",
       "       [7., 8.]])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([[1.,2.],[4.,5.],[7.,8.]])\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 4., 7.],\n",
       "       [2., 5., 8.]])"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = np.stack(a,-1) #J: A = hcat(a...)\n",
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 2.],\n",
       "       [4., 5.],\n",
       "       [7., 8.]])"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = np.stack(a,1) #J: A = vcat(a...)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/vb/anaconda3/lib/python3.7/site-packages/networkx/drawing/nx_pylab.py:611: MatplotlibDeprecationWarning: isinstance(..., numbers.Number)\n",
      "  if cb.is_numlike(alpha):\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "#detour from companion to sketch adjacency matrix example from p112 of VMLS\n",
    "import networkx as nx\n",
    "pg112 = np.matrix([[0,1,1,0],[1,0,0,1],[0,0,0,1],[1,0,0,0]])\n",
    "G = nx.from_numpy_matrix(pg112)\n",
    "pos = nx.layout.spring_layout(G)\n",
    "node_sizes = [3 + 10 * i for i in range(len(G))]\n",
    "M = G.number_of_edges()\n",
    "edge_colors = range(2, M + 2)\n",
    "edge_alphas = [(5 + i) / (M + 4) for i in range(M)]\n",
    "\n",
    "nodes = nx.draw_networkx_nodes(G, pos, node_size=node_sizes, node_color='blue', with_labels=True)\n",
    "edges = nx.draw_networkx_edges(G, pos, node_size=node_sizes, arrowstyle='->',\n",
    "                               arrowsize=10, edge_color=edge_colors,\n",
    "                               edge_cmap=plt.cm.Blues, width=2)\n",
    "\n",
    "ax = plt.gca()\n",
    "ax.set_axis_off()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 6.2 Zero and Identity Matrices"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 0.],\n",
       "       [0., 0.]])"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.zeros((2,2)) #J: zeros(2,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 0., 0., 0.],\n",
       "       [0., 1., 0., 0.],\n",
       "       [0., 0., 1., 0.],\n",
       "       [0., 0., 0., 1.]])"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = np.identity(4)\n",
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1., -1.,  2.,  1.,  0.],\n",
       "       [ 0.,  3., -1.,  0.,  1.]])"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = np.array([[1,-1,2],[0,3,-1]])\n",
    "np.hstack([A, np.identity(np.shape(A)[0])]) #J: [A I]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1., -1.,  2.],\n",
       "       [ 0.,  3., -1.],\n",
       "       [ 1.,  0.,  0.],\n",
       "       [ 0.,  1.,  0.],\n",
       "       [ 0.,  0.,  1.]])"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = np.array([[1,-1,2],[0,3,-1]])\n",
    "np.vstack([A,np.identity(np.shape(A)[1])]) #J: [A; I]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2., 2.],\n",
       "       [3., 5.]])"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B = np.array([[1,2],[3,4]])\n",
    "B+np.identity(np.shape(B)[0]) #J: B+I"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 0, 0],\n",
       "       [0, 2, 0],\n",
       "       [0, 0, 3]])"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.diag([1,2,3]) #J: diagm(0=>x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0],\n",
       "       [-1]])"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "H = np.matrix([[0,1,-2,1],[2,-1,3,0]])\n",
    "H\n",
    "np.vstack(np.diag(H)) #J: diag(H)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[0.71192781, 0.47114325, 0.43761741],\n",
       "        [0.46379698, 0.02508166, 0.94181704]]),\n",
       " array([[ 0.66952997, -0.4726436 ],\n",
       "        [ 0.32564393,  0.05696981],\n",
       "        [ 0.99898489, -2.77258862]]))"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.random.rand(2,3), np.random.randn(3,2) #J: rand(2,3), randn(3,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "I = np.array([1,2,2,1,3,4]) #rows\n",
    "J = np.array([1,1,2,3,3,4]) #cols\n",
    "V = np.array([-1.11,.15,-.1, 1.17, -.3,.13]) #data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.  ,  1.  , -1.11],\n",
       "       [ 2.  ,  1.  ,  0.15],\n",
       "       [ 2.  ,  2.  , -0.1 ],\n",
       "       [ 1.  ,  3.  ,  1.17],\n",
       "       [ 3.  ,  3.  , -0.3 ],\n",
       "       [ 4.  ,  4.  ,  0.13]])"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from scipy.sparse import csc_matrix, rand, find\n",
    "csc_matrix([I,J,V]).toarray().transpose() #J: A = sparse(I,J,V,4,5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[1., 1., 1.],\n",
       "        [3., 1., 2.],\n",
       "        [2., 2., 3.],\n",
       "        [1., 3., 4.]]), 12)"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = csc_matrix([[1,3,2,1],[1,1,2,3],[1.0,2.0,3.0,4.0]]).transpose()\n",
    "A.toarray(), np.count_nonzero(A.toarray())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Not sure what's going on on page 53 final example of returning a 3x3 non-sparse matrix \n",
    "#looks like it takes the 4x1 RHS of the sparse matrix and shapes it into a 3x3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = rand(10000,10000,density=10**-7, format='csc')\n",
    "A.nnz"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([9689, 7482, 7004,   36,  407, 5229, 5320, 1444,   89, 6790],\n",
       "       dtype=int32),\n",
       " array([ 929, 1686, 1754, 3614, 3758, 4317, 5928, 6008, 8063, 8970],\n",
       "       dtype=int32),\n",
       " array([0.8338679 , 0.6495291 , 0.99773722, 0.01514599, 0.20570428,\n",
       "        0.10445821, 0.9333198 , 0.02056975, 0.78049289, 0.03074935]))"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "find(A)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 6.3 Transpose, Addition, Norm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1, -2,  1],\n",
       "       [ 2, -1,  3,  0]])"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "H = np.array([[0,1,-2,1],[2,-1,3,0]])\n",
    "H"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  2],\n",
       "       [ 1, -1],\n",
       "       [-2,  3],\n",
       "       [ 1,  0]])"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "H.transpose() #J : H'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[0, 4],\n",
       "        [7, 0],\n",
       "        [3, 1]]), array([[1, 2],\n",
       "        [2, 3],\n",
       "        [0, 4]]))"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "U,V = np.array([[0,4],[7,0],[3,1]]),np.array([[1,2],[2,3],[0,4]])\n",
    "U, V"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[1, 6],\n",
       "        [9, 3],\n",
       "        [3, 5]]), array([[ 0. ,  8.8],\n",
       "        [15.4,  0. ],\n",
       "        [ 6.6,  2.2]]))"
      ]
     },
     "execution_count": 69,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "U+V, 2.2*U "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(5.5677643628300215, 5.5677643628300215)"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#matrix norms\n",
    "A = np.array([[2,3,-1],[0,-1,4]])\n",
    "npl.norm(A), npl.norm(A[:])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(4.69041575982343, 7.795831523312719)"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#triangle inequality\n",
    "A,B = np.array([[-1,0],[2,2]]),np.array([[3,1],[-3,2]])\n",
    "npl.norm(A+B), npl.norm(A)+npl.norm(B)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 6.4 Matrix-Vector Multiplication"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 3, -4])"
      ]
     },
     "execution_count": 90,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A,x = np.array([[0,2,-1],[-2,1,1]]), np.array([2,1,-1])\n",
    "np.matmul(A,x) #J: A*x, which in python returns a 2x3 with A values multiplied by x values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 137,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-1.,  1.,  0.,  0.],\n",
       "       [ 0., -1.,  1.,  0.],\n",
       "       [ 0.,  0., -1.,  1.]])"
      ]
     },
     "execution_count": 137,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#c_ is an np method for adding a column. \n",
    "#J equiv: [-eye zeros] automatically adds column wise\n",
    "difference_matrix = lambda n: np.c_[-np.identity(n-1), np.zeros(n-1)] + np.c_[np.zeros(n-1), np.eye(n-1)] \n",
    "D = difference_matrix(4)\n",
    "D"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 144,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1.,  2., -1.])"
      ]
     },
     "execution_count": 144,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.matmul(D,np.array([-1,0,2,1]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 148,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 0., 0.],\n",
       "       [0., 1., 0.],\n",
       "       [0., 0., 1.]])"
      ]
     },
     "execution_count": 148,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#don't know what the sparse identity matrix is doing on 57"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 195,
   "metadata": {},
   "outputs": [],
   "source": [
    "#running sum\n",
    "def running_sum(n):\n",
    "    S = np.zeros((n,n))\n",
    "    for i in range(n):\n",
    "        for j in range(i+1): #0 indexing fix to get diags = 1\n",
    "            S[i,j] = 1\n",
    "            \n",
    "    return S"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 197,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[1., 0., 0., 0.],\n",
       "        [1., 1., 0., 0.],\n",
       "        [1., 1., 1., 0.],\n",
       "        [1., 1., 1., 1.]]), array([-1.,  0.,  2.,  2.]))"
      ]
     },
     "execution_count": 197,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "running_sum(4),np.matmul(running_sum(4),np.array([-1,1,2,0]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 202,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[1., 0., 0., 0.],\n",
       "        [1., 1., 0., 0.],\n",
       "        [1., 1., 1., 0.],\n",
       "        [1., 1., 1., 1.]]), [1.0, 2.0, 3.0, 4.0])"
      ]
     },
     "execution_count": 202,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#tril implementation #J: tril(ones(n,n))\n",
    "#also running sum test\n",
    "sum_test_list = np.tril(np.ones((4,4)))\n",
    "np.tril(np.ones((4,4))), [np.sum(i) for i in sum_test_list]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 217,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.    , -1.    ,  1.    , -1.    ,  1.    ],\n",
       "       [ 0.    ,  0.    ,  0.    ,  0.    ,  1.    ],\n",
       "       [ 0.0625,  0.125 ,  0.25  ,  0.5   ,  1.    ],\n",
       "       [ 1.    ,  1.    ,  1.    ,  1.    ,  1.    ]])"
      ]
     },
     "execution_count": 217,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.vander([-1,-0,0.5,1],5) #col-wise reverse to vander in Julia?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 249,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.    , -1.    ,  1.    , -1.    ,  1.    ],\n",
       "       [ 1.    ,  0.    ,  0.    ,  0.    ,  0.    ],\n",
       "       [ 1.    ,  0.5   ,  0.25  ,  0.125 ,  0.0625],\n",
       "       [ 1.    ,  1.    ,  1.    ,  1.    ,  1.    ]])"
      ]
     },
     "execution_count": 249,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#credits wolfram:\n",
    "#Vandermonde matrices are:\n",
    "#\"a type of matrix that arises in the polynomial least squares fitting, \n",
    "#Lagrange interpolating polynomials (Hoffman and Kunze p. 114), \n",
    "#and the reconstruction of a statistical distribution from the \n",
    "#distribution's moments [mean, variance, skewness, kurtosis (sharpness)]\"\n",
    "def vander(t,n):\n",
    "    m = len(t)\n",
    "    V = np.zeros((m,n))\n",
    "    for i in range(m):\n",
    "        for j in range(n):\n",
    "            V[i,j] = t[i]**(j)\n",
    "    return V\n",
    "\n",
    "#ie: \n",
    "# vander = lambda t,n : np.matrix([[i**(j) for i in t] for j in range(n)]).transpose()\n",
    "#or\n",
    "# vander = lambda t,n : np.vstack([np.array(t)**i for i in range(n)]).transpose()\n",
    "vander([-1,-0,0.5,1],5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 6.5 Complexity"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 254,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3.62 ms ± 40.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "A,x = np.random.rand(1000,10000), np.random.rand(10000)\n",
    "%timeit y=np.matmul(A,x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 255,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3.52 ms ± 60.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit y=np.matmul(A,x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 256,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "40 ms ± 641 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
     ]
    }
   ],
   "source": [
    "A,x = np.random.rand(5000,20000), np.random.rand(20000)\n",
    "%timeit y=np.matmul(A,x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 257,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "39.4 ms ± 956 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
     ]
    }
   ],
   "source": [
    "%timeit y=np.matmul(A,x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Complexity of multiplying m x n matrix with an n vector is linear with both m and n, we see a factor of 10 time increase given a factor of of 5 and 2 for m and n increasing"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
